home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <alloc.h>
- #include <dos.h>
- #include <string.h>
-
- #include "global.h"
- #include "memoria.h"
- #include "video.h"
- #include "tiff.h"
- #include "error.h"
-
- /* Nombres de las etiquetas, estan todas las de la version TIFF 5.00 */
- #define NewSubfileType 254
- #define SubfileType 255
- #define ImageWidth 256
- #define ImageLength 257
- #define BitsPerSample 258
- #define Compression 259
- #define PhotometricInterp 262
- #define Threshholding 263
- #define CellWidth 264
- #define CellLength 265
- #define FillOrder 266
- #define DocumentName 269
- #define ImageDescription 270
- #define Make 271
- #define Model 272
- #define StripOffsets 273
- #define Orientation 274
- #define SamplesPerPixel 277
- #define RowsPerStrip 278
- #define StripByteCounts 279
- #define MinSampleValue 280
- #define MaxSampleValue 281
- #define XResolution 282
- #define YResolution 283
- #define PlanarConfiguration 284
- #define Pagename 285
- #define XPosition 286
- #define YPosition 287
- #define FreeOffsets 288
- #define FreeByteCounts 289
- #define GrayResponseUnit 290
- #define GrayResponseCurve 291
- #define Group3Options 292
- #define Group4Options 293
- #define ResolutionUnit 296
- #define PageNumber 297
- #define ColorResponseUnit 300
- #define ColorResponseCurves 301
- #define Software 305
- #define DateTime 306
- #define Artist 315
- #define HostComputer 316
- #define Predictor 317
- #define WhitePoint 318
- #define PrimaryChromaticities 319
- #define Colormap 320
-
- /* tipos de tags */
- #define TIFFbyte 1
- #define TIFFascii 2
- #define TIFFshort 3
- #define TIFFlong 4
- #define TIFFrational 5
-
- /* Tipos de compresion de ficheros */
- #define COMPno 1 /* sin comprimir */
- #define COMPhuff 2 /* CCITT 3, Metodo Huffman */
- #define COMPfax3 3 /* Facsimile CCITT group 3 */
- #define COMPfax4 4 /* Facsimile CCITT group 4 */
- #define COMPlzw 5 /* LZW */
- #define COMPmpnt 0x8005 /* PackBits o MacPaint */
-
- /* clases de ficheros TIFF */
- #define TIFFclaseX 0 /* generico */
- #define TIFFclaseB 1 /* blanco y negro */
- #define TIFFclaseG 2 /* gris */
- #define TIFFclaseP 3 /* paleta de color */
- #define TIFFclaseR 4 /* RGB */
-
- /* variables para albergar los valores de los tags */
- int TIFFclase;
- unsigned int TIFFancho=0,TIFFalto=0,TIFFbytes=0;
- unsigned int TIFFformato=0;
- unsigned int TIFFsubfile=0;
- unsigned int TIFFsamples=1;
- unsigned int TIFFbitspersample=1;
- unsigned int TIFFplancfg=1;
- unsigned int TIFFcompres=1;
- unsigned int TIFFphotmet=0;
- unsigned long TIFFrowstrip=0L;
- unsigned long TIFFstripoff=0L;
- unsigned long TIFFstripcnt=0L;
- int TIFFcolores;
- char *TIFFpaleta = NULL;
-
- IMAGEN *TIFFleerCabecera(IMAGEN *c,FILE *f,char *nombre);
- int TIFFleerTag(FILE *f);
- int TIFFleerclase(void);
- IMAGEN *TIFFleerImagen(IMAGEN *c,FILE *f);
- int TIFFleerLinea(char *p,FILE *f,int bytes);
- unsigned long TIFFleerLong(FILE *f);
- unsigned int TIFFleerWord(FILE *f);
-
- void TIFFescribirCabecera(FILE *f);
- void TIFFescribirDirectorio(IMAGEN *c,FILE *f,long LugarDirectorio,long LugarPaleta,long LugarImagen);
- void TIFFescribirTAG(FILE *f,int tag,int tipo,long longitud,long desplazamiento);
- void TIFFescribirImagen(IMAGEN *c,FILE *f);
- void TIFFescribirLinea(char *p,FILE *f,int bytes);
- void TIFFescribirWord(FILE *f,int n);
- void TIFFescribirLong(FILE *f,long n);
-
- extern IMAGEN *TIFFcargar(char *nombre,IMAGEN *c)
- {
- /* puntero al fichero */
- FILE *f;
-
- /* abrir el fichero */
- if((f=fopen(nombre,"rb"))!=NULL)
- {
- /* leer cabecera */
- if((c=TIFFleerCabecera(c,f,nombre))!=NULL)
- /* leer imagen */
- c = TIFFleerImagen(c,f);
- fclose(f);
- }
- else
- {
- ERRORponer(ERRapertura);
- return(NULL);
- }
- return(c);
- }
-
- IMAGEN *TIFFleerCabecera(IMAGEN *c,FILE *f,char *nombre)
- {
- /* contador */
- int i;
- /* tags del directorio */
- unsigned int TIFFtotalTags=0;
-
- /* leer formato INTEL o MOTOROLA */
- TIFFformato=TIFFleerWord(f);
- if(TIFFformato != 'MM' && TIFFformato != 'II')
- {
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
-
- /* comprobar que es un fichero TIFF */
- if(TIFFleerWord(f) != 42)
- {
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
-
- /* posicionar para leer el primer IFD */
- fseek(f,TIFFleerLong(f),SEEK_SET);
- /* leer los TAGs del IFD */
- TIFFtotalTags=TIFFleerWord(f);
- for(i=0;i<TIFFtotalTags;++i)
- TIFFleerTag(f);
-
- /* si no se acepta el tipo de fichero o de compresion */
- if(TIFFsubfile || (TIFFcompres != COMPno && TIFFcompres != COMPmpnt))
- {
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
-
- /* reservar memoria para la cabecera de trabajo */
- if((c=MEMreservarCAB(c))==NULL)
- {
- ERRORponer(ERRnoMemoria);
- return(NULL);
- }
-
- /* obtener el clase de fichero TIFF y cargar la cabecera de trabajo */
- TIFFclase = TIFFleerclase();
- switch(TIFFclase)
- {
- /* monocromo */
- case TIFFclaseB:
- c->colores = 2;
- c->modo = VIDEOmono;
- c->bytes = TIFFbytes;
- c->haypaleta = FALSO;
- break;
-
- /* color o tonos de gris */
- case TIFFclaseG:
- case TIFFclaseP:
- c->colores = TIFFcolores;
- c->modo = VIDEOvga;
- c->bytes = TIFFbytes;
- /* si hay paleta, leerla */
- if(TIFFpaleta!= NULL)
- {
- memcpy(c->paleta,TIFFpaleta,c->colores*3);
- free(TIFFpaleta);
- c->haypaleta = CIERTO;
- }
- else
- c->haypaleta = FALSO;
- break;
- /* RGB u otros */
- default:
- ERRORponer(ERRnoTratado);
- c = MEMliberar(c);
- return(c);
- }
-
- /* cargar el resto de la cabecera de trabajo */
- strcpy(c->nombre,nombre);
- c->ancho = TIFFancho;
- c->alto = TIFFalto;
- c->formato = TIFF;
-
- /* si no hay memoria para la imagen, liberar cabecera */
- if(!MEMreservar(c))
- {
- c = MEMliberar(c);
- ERRORponer(ERRnoMemoria);
- return(c);
- }
- return(c);
- }
-
- IMAGEN *TIFFleerImagen(IMAGEN *c,FILE *f)
- {
- long l;
- int i,j,b;
- char p[ANCHO_MAXIMO];
-
- switch(TIFFclase)
- {
- /* monocroma */
- case TIFFclaseB:
- /* si hay un solo bloque */
- if(TIFFstripcnt==1L)
- {
- /* posicionar al inicio de la imagen */
- fseek(f,TIFFstripoff,SEEK_SET);
- /* leer imagen */
- for(i=0;i<c->alto;++i)
- {
- TIFFleerLinea(p,f,c->bytes);
- MEMescribir(p,i,c);
- }
- }
- else
- /* si son varios */
- {
- i=0;
- for(l=0L;l<TIFFstripcnt;++l)
- {
- /* posicionar el puntero al inicio del bloque */
- fseek(f,TIFFstripoff+(l*sizeof(long)),SEEK_SET);
- fseek(f,TIFFleerLong(f),SEEK_SET);
- /* leer bloque */
- for(j = 0;j<TIFFrowstrip;j++)
- {
- TIFFleerLinea(p,f,c->bytes);
- MEMescribir(p,i++,c);
- }
- }
- }
- break;
- /* color o gris */
- case TIFFclaseP:
- case TIFFclaseG:
- if(TIFFbitspersample == 4)
- b = c->bytes/2;
- else
- b = c->bytes;
- /* si hay un solo bloque */
- if(TIFFstripcnt==1L)
- {
- /* posicionar puntero al inicio de la imagen */
- fseek(f,TIFFstripoff,SEEK_SET);
- for(i=0;i<c->alto;++i)
- {
- TIFFleerLinea(p,f,b);
- MEMescribir(p,i,c);
- }
- }
- else
- /* si hay varios bloques */
- {
- i=0;
- for(l=0L;l<TIFFstripcnt;++l)
- {
- /* posicionar puntero al inicio del bloque */
- fseek(f,TIFFstripoff+(l*sizeof(long)),SEEK_SET);
- fseek(f,TIFFleerLong(f),SEEK_SET);
- /* leer bloque */
- for(j = 0;j<TIFFrowstrip;j++)
- {
- TIFFleerLinea(p,f,b);
- MEMescribir(p,i++,c);
- }
- }
- }
- break;
- };
- return(c);
- }
-
- int TIFFleerLinea(char *p,FILE *f,int bytes)
- {
- int i,n=0,c;
- char buffer[ANCHO_MAXIMO];
- memset(p,0,bytes);
- memset(buffer,0,ANCHO_MAXIMO);
-
- switch(TIFFcompres)
- {
- /* sin comprimir */
- case COMPno:
- /* leer línea */
- n=fread(buffer,1,bytes,f);
- /* si es preciso, invertir línea */
- if(TIFFphotmet==0)
- for(i=0;i<bytes;++i)
- *(buffer+i)=~(*(buffer+i));
- /* si hay 4 bits por pixel, extraer dos pixels de cada byte */
- if(TIFFbitspersample == 4)
- for(i=0,c=0;i<bytes;i++,c+=2)
- {
- p[c+1] = buffer[i] & 0x0f;
- p[c] = (buffer[i] & 0xf0) >> 4;
- }
- else
- memcpy(p,buffer,bytes);
- break;
-
- /* Pacbits o MacPaint */
- case COMPmpnt:
- do
- {
- /* leer byte */
- c=fgetc(f) & 0xff;
- /* si el bit 7 es 1 */
- if(c & 0x80)
- {
- /* contador */
- i=((~c) & 0xff)+2;
- c=fgetc(f);
- if(TIFFphotmet==0)
- while(i--)
- buffer[n++]=~c;
- else
- while(i--)
- buffer[n++]=c;
- }
- else
- {
- /* contador */
- i=(c &0xff)+1;
- if(TIFFphotmet==0)
- while(i--)
- buffer[n++]=~fgetc(f);
- else
- while(i--)
- buffer[n++]=fgetc(f);
- }
- }
- while(n < bytes);
- /* si hay 4 bits por pixel, extraer dos pixels de cada byte */
- if(TIFFbitspersample == 4)
- for(i=0,c=0;i<bytes;i++,c+=2)
- {
- p[c+1] = buffer[i] & 0x0f;
- p[c] = (buffer[i] & 0xf0) >> 4;
- }
- else
- memcpy(p,buffer,bytes);
- break;
- };
- return(n);
- }
-
- int TIFFleerTag(FILE *f)
- {
- /* numero del tag */
- int tag;
- /* tipo de tag */
- int tipo;
- /* longitud del tag */
- long longitud;
- /* puntero al dato o valor */
- long desplazamiento;
- /* contadores */
- int i,j;
- /* puntero a paleta auxiliar */
- char *paux;
-
- /* leer número del tag */
- tag=TIFFleerWord(f);
- /* leer tipo del tag */
- tipo = TIFFleerWord(f);
- /* extraer longitud y desplazamiento (o valor) */
- switch(tipo)
- {
- case TIFFbyte:
- longitud=(unsigned long)fgetc(f);
- for(i=0;i<3;i++) fgetc(f);
- desplazamiento=(unsigned long)fgetc(f);
- for(i=0;i<3;i++) fgetc(f);
- break;
- case TIFFshort:
- longitud=(unsigned long)TIFFleerWord(f);
- TIFFleerWord(f);
- desplazamiento=(unsigned long)TIFFleerWord(f);
- TIFFleerWord(f);
- break;
- default:
- longitud=TIFFleerLong(f);
- desplazamiento=TIFFleerLong(f);
- break;
- };
- /* tratar tag */
- switch(tag)
- {
- case NewSubfileType:TIFFsubfile=(unsigned int)desplazamiento;break;
- case ImageWidth:TIFFancho=(unsigned int)desplazamiento;break;
- case ImageLength:TIFFalto=(unsigned int)desplazamiento;break;
- case RowsPerStrip:
- /* filas por bloque */
- if(tipo==TIFFlong)
- TIFFrowstrip=desplazamiento;
- else
- TIFFrowstrip=desplazamiento & 0xffffL;
- break;
- case StripOffsets:
- /* desplazamiento de bloque */
- if(tipo==TIFFlong)
- {
- TIFFstripoff=desplazamiento;
- TIFFstripcnt=longitud;
- }
- else
- {
- TIFFstripoff=desplazamiento & 0xffffL;
- TIFFstripcnt=desplazamiento & 0xffffL;
- }
- break;
- case SamplesPerPixel:TIFFsamples=(unsigned int)desplazamiento;break;
- case BitsPerSample:TIFFbitspersample=(unsigned int )desplazamiento;break;
- case PlanarConfiguration:TIFFplancfg=(unsigned int)desplazamiento;break;
- case Compression:TIFFcompres=(unsigned int)desplazamiento;break;
- case PhotometricInterp:TIFFphotmet=(unsigned int)desplazamiento;break;
- case Colormap:
- /* paleta de colores */
- fseek(f,desplazamiento,SEEK_SET);
- TIFFcolores = 1 << TIFFbitspersample;
- TIFFpaleta = malloc(TIFFcolores*3);
- /* leer las tres subcurvas */
- for(j=0;j<3;j++)
- {
- paux = TIFFpaleta+j;
- /* los valores RGB vienen como enteros */
- for(i=0;i<TIFFcolores;++i,paux+=3)
- {fgetc(f); *paux = fgetc(f);}
- }
- break;
- /* tag desconocido o no tratado */
- default:break;
- };
- return(tag);
- }
-
- int TIFFleerclase(void)
- {
- /* clase no tratada */
- if(TIFFsamples!=1 || TIFFplancfg!=1)
- return(TIFFclaseX);
-
- switch(TIFFbitspersample)
- {
- /* monocromos, 1 bit por pixel */
- case 1:
- TIFFbytes = DePixelsABytes(TIFFancho);
- TIFFcolores = 2;
- return(TIFFclaseB);
- /* gris o color, 4 u 8 bits por pixel */
- case 4:
- case 8:
- /* determinar número de colores o grises */
- TIFFcolores = 1 << TIFFbitspersample;
- TIFFbytes = TIFFancho;
- /* gris */
- if(TIFFphotmet == 0 || TIFFphotmet == 1)
- return(TIFFclaseG);
- /* paleta de color */
- else if(TIFFphotmet == 3)
- return(TIFFclaseP);
- /* RGB */
- else if(TIFFphotmet == 2)
- {
- TIFFbytes = TIFFancho * 3;
- return(TIFFclaseR);
- }
- /* desconocido o no tratado */
- else return(TIFFclaseX);
- default: return(TIFFclaseX);
- };
- }
-
- unsigned int TIFFleerWord(FILE *f)
- {
- /* INTEL */
- if(TIFFformato == 'II')
- return((fgetc(f) & 0xff) + ((fgetc(f) & 0xff) << 8));
- /* MOTOROLA */
- else
- return(((fgetc(f) & 0xff) << 8) + (fgetc(f) & 0xff));
- }
-
- unsigned long TIFFleerLong(FILE *f)
- {
- /* INTEL */
- if(TIFFformato == 'II')
- return((unsigned long)(fgetc(f) & 0xff) +
- ((unsigned long)(fgetc(f) & 0xff) << 8)+
- ((unsigned long)(fgetc(f) & 0xff) << 16)+
- ((unsigned long)(fgetc(f) & 0xff) << 24));
- /* MOTOROLA */
- else
- return(((unsigned long)(fgetc(f) & 0xff) << 24)+
- ((unsigned long)(fgetc(f) & 0xff) << 16)+
- ((unsigned long)(fgetc(f) & 0xff) << 8)+
- (unsigned long)(fgetc(f) & 0xff));
- }
-
-
- /* salvar un fichero TIFF */
- extern int TIFFsalvar(char *fichero,IMAGEN *c)
- {
- /* puntero al fichero */
- FILE *f;
- /* contadores */
- int i,j;
- /* puntero auxiliar a paleta */
- char *paux;
- /* desplazamientos */
- long TIFFlugarDirectorio;
- long TIFFlugarPaleta;
- long TIFFlugarImagen;
- /* ajuste de colores */
- int colores;
-
- /* abrir el fichero */
- if((f = fopen(fichero, "wb")) == NULL)
- {
- ERRORponer(ERRapertura);
- return(0);
- }
-
- /* adecuar modo de video */
- if(c->modo == VIDEOvga && c->colores <= 16)
- c = VIDEOvision(c);
-
- /* escribir la cabecera TIFF */
- TIFFescribirCabecera(f);
- TIFFlugarPaleta = ftell(f);
-
- /* si es de color, escribir paleta TIFF */
- if(c->modo != VIDEOmono)
- {
- /* ajustar colores */
- colores = (c->modo == VIDEOega) ? 16 : 256;
- /* escribir las 3 subcurvas */
- for(j=0;j<3;j++)
- {
- paux = c->paleta+j;
- for(i=0;i<colores;i++,paux+=3)
- {
- /* cada componente ocupa dos bytes */
- fputc(0,f);
- fputc(*paux,f);
- }
- }
- }
-
- /* escribir la imagen TIFF */
- TIFFlugarImagen = ftell(f);
- TIFFescribirImagen(c,f);
- /* escribir directorio de TAGS */
- TIFFlugarDirectorio = ftell(f);
- TIFFescribirDirectorio(c,f,TIFFlugarDirectorio,TIFFlugarPaleta,TIFFlugarImagen);
- fclose(f);
- return(1);
- }
-
- void TIFFescribirCabecera(FILE *f)
- {
- TIFFescribirWord(f,'II');
- TIFFescribirWord(f,42);
- TIFFescribirLong(f,0L);
- }
-
- void TIFFescribirDirectorio(IMAGEN *c,FILE *f,long LugarDirectorio,long LugarPaleta,long LugarImagen)
- {
- unsigned int TIFFtotalTags=0;
-
- /* puntero al fichero para recordar el offset */
- switch(c->modo)
- {
- case VIDEOmono:
- /* 7 TAGS */
- TIFFtotalTags=7;
- TIFFescribirWord(f,TIFFtotalTags);
- TIFFescribirTAG(f,ImageWidth,TIFFshort,0L,(long)c->ancho);
- TIFFescribirTAG(f,ImageLength,TIFFshort,0L,(long)c->alto);
- TIFFescribirTAG(f,BitsPerSample,TIFFshort,0L,1L);
- TIFFescribirTAG(f,Compression,TIFFshort,0L,(long)COMPno);
- TIFFescribirTAG(f,PhotometricInterp,TIFFshort,0L,1L);
- TIFFescribirTAG(f,StripOffsets,TIFFlong,1L,LugarImagen);
- TIFFescribirTAG(f,PlanarConfiguration,TIFFshort,1L,1L);
- break;
- case VIDEOega:
- TIFFtotalTags=8;
- TIFFescribirWord(f,TIFFtotalTags);
- TIFFescribirTAG(f,ImageWidth,TIFFshort,0L,(long)c->ancho);
- TIFFescribirTAG(f,ImageLength,TIFFshort,0L,(long)c->alto);
- TIFFescribirTAG(f,BitsPerSample,TIFFshort,1L,4L);
- TIFFescribirTAG(f,Compression,TIFFshort,0L,(long)COMPno);
- TIFFescribirTAG(f,PhotometricInterp,TIFFshort,0L,3L);
- TIFFescribirTAG(f,StripOffsets,TIFFlong,1L,LugarImagen);
- TIFFescribirTAG(f,PlanarConfiguration,TIFFshort,1L,1L);
- TIFFescribirTAG(f,Colormap,TIFFshort,(long)c->colores*6L,LugarPaleta);
- break;
- case VIDEOvga:
- TIFFtotalTags=8;
- TIFFescribirWord(f,TIFFtotalTags);
- TIFFescribirTAG(f,ImageWidth,TIFFshort,0L,(long)c->ancho);
- TIFFescribirTAG(f,ImageLength,TIFFshort,0L,(long)c->alto);
- TIFFescribirTAG(f,BitsPerSample,TIFFshort,1L,8L);
- TIFFescribirTAG(f,Compression,TIFFshort,0L,(long)COMPno);
- TIFFescribirTAG(f,PhotometricInterp,TIFFshort,0L,3L);
- TIFFescribirTAG(f,StripOffsets,TIFFlong,1L,LugarImagen);
- TIFFescribirTAG(f,PlanarConfiguration,TIFFshort,1L,1L);
- TIFFescribirTAG(f,Colormap,TIFFshort,(long)c->colores*6L,LugarPaleta);
- break;
- };
- /* escribir inicio del IFD */
- TIFFescribirLong(f,0L);
- fseek(f,4l,SEEK_SET);
- TIFFescribirLong(f,LugarDirectorio);
- }
-
- void TIFFescribirTAG(FILE *f,int tag,int tipo,long longitud,long desplazamiento)
- {
- TIFFescribirWord(f,tag);
- TIFFescribirWord(f,tipo);
- TIFFescribirLong(f,longitud);
- TIFFescribirLong(f,desplazamiento);
- }
-
- void TIFFescribirImagen(IMAGEN *c,FILE *f)
- {
- /* contador líneas */
- int i;
- /* buffers */
- char p[ANCHO_MAXIMO];
- char q[ANCHO_MAXIMO];
- /* salvar imagen */
- switch(c->modo)
- {
- case VIDEOmono:
- case VIDEOvga:
- for(i=0;i<c->alto;++i)
- {
- MEMleer(p,i,c);
- TIFFescribirLinea(p,f,c->bytes);
- }
- break;
-
- /* si la imagen es EGA, convertir de plano a pixel */
- case VIDEOega:
- for(i=0;i<c->alto;++i)
- {
- MEMleer(q,i,c);
- EGAdePlanoaPixel(q,p,c->ancho);
- TIFFescribirLinea(p,f,c->bytes);
- }
- break;
- };
- }
-
- void TIFFescribirLinea(char *p,FILE *f,int bytes)
- {
- fwrite(p,bytes,1,f);
- }
-
- void TIFFescribirWord(FILE *f,int n)
- {
- fputc(n,f);
- fputc(n>>8,f);
- }
-
- void TIFFescribirLong(FILE *f,long n)
- {
- fputc((int)n,f);
- fputc((int)(n>>8),f);
- fputc((int)(n>>16),f);
- fputc((int)(n>>24),f);
- }